package server

import (
	"gitee.com/sdynasty/clever/clog"
	"gitee.com/sdynasty/clever/server/router"
	"gitee.com/sdynasty/clever/sessions"
	"gitee.com/sdynasty/clever/socket"
	"github.com/gorilla/websocket"
	"net"
	"net/http"
)

var (
	CtrServer *CentreServer
	upgrader = websocket.Upgrader{
		// 允许跨域
		CheckOrigin:func(r *http.Request) bool{
			return true
		},
	}
)

const (
	MaxConnect = 1000000000
)

type CentreServer struct {
	SessionMgr      *sessions.SessionMgr
	ProtoRouterPool *router.ProtoRouter
	MessageRouter   IRouter
	fd              uint32
}

// 创建网络服务
func newTcpSocketNetwork(r IRouter) *CentreServer {
	sessMgr := sessions.NewSessionMgr()
	s := &CentreServer{
		SessionMgr:      sessMgr,
		ProtoRouterPool: router.NewRouter(),
		MessageRouter:   r,
		fd:              0,
	}
	return s
}

// 创建socket server
func CreateNetServer(r IRouter) *CentreServer {
	CtrServer = newTcpSocketNetwork(r)
	clog.LogNetwork().Println("Created centre network")
	return CtrServer
}

// 启动服务
func (this *CentreServer) Start(address string) {
	clog.LogNetwork().Println("centre network started")
	go StartMQ(this)
	go this.listening(address)
}

// 启动监听
func (this *CentreServer) listening(address string) {
	// 绑定网络端口
	tcpListen, err := net.Listen("tcp", address)
	if err != nil {
		panic(err)
	}

	clog.LogNetwork().Println("start listening at ", address)
	for {
		conn, err := tcpListen.Accept()
		if err != nil {
			clog.LogNetwork().Println(err)
			continue
		}

		clog.LogNetwork().Println("new tcp Accept")

		if this.SessionMgr.IsFdUsed(this.fd) {
			this.fd ++
			if this.fd > MaxConnect {
				this.fd = 0
			}
		}
		fd := this.fd

		clog.LogNetwork().Info("listening accept fd=", fd)
		connNet, err := socket.InitNetConnection(conn, fd, MQ)
		if err != nil {
			clog.LogNetwork().Error("socket.InitNetConnection err = ", err)
			conn.Close()
			continue
		}
		// 生成新的Session
		this.SessionMgr.SetSessionWithTCP(fd, connNet)
		clog.LogNetwork().Debug("listening SetSessionWithTCP fd: ", fd)
	}
}

// 消息接口
func (this *CentreServer) OnMessage(fd uint32, data []byte) {
	sess := this.SessionMgr.GetSessionByFd(fd)
	if sess != nil {
		this.MessageRouter.HandleMessage(sess, data)
		// session 的转换是重点
		//this.ProtoRouterPool.HandleMessage(sess, data)
	} else {
		clog.LogNetwork().Error("OnMessage session got nil, fd:", fd)
	}
}

// 客户端网络断开
func (this *CentreServer) OnNetworkBroken(fd uint32) {
	sess := this.SessionMgr.GetSessionByFd(fd)
	if sess != nil {
		clog.LogNetwork().Debug("客户端网络断开 got sess.  IsSignIn: ", sess.IsSignIn())

		if sess.IsSignIn() {
			// 如果已经登录 通知逻辑服
			//data := util.EncodePb(&pb.PBInt{
			//	Value: sess.GetUserData().Uid,
			//}, 0, true)
			data := []byte{}

			this.MessageRouter.HandleMessage(sess, data)
		} else {
			this.SessionMgr.DeleteSession(fd, 0, "")
		}
	} else {
		clog.LogNetwork().Debugf("客户端网络断开 can`t find sess fd:%d\n", fd)
	}
}